/*
 *    Copyright 2014 Sam Y Ge
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.strx;

/**
 * <p>
 * 标签读取器
 * </p>
 * 
 * <p>
 * 继承该读取器的类必须实现标签读取方法getNextTag()
 * </p>
 * 
 * @author <a href="mailto:samuel.y@foxmail.com">Sam Y Ge</a>
 */
abstract class TagReader {
	/** 当前最后一次读取到的Tag字符串 */
	protected String currTagStr;

	/** 当前最后一次读取到的Tag */
	protected Tag currTag;

	/**
	 * <p>
	 * 读取下一个标签
	 * </p>
	 * 
	 * <p>
	 * 继承该读取器的类必须实现该方法
	 * </p>
	 * 
	 * @return 读取到的标签,当无标签可读时，返回null
	 */
	abstract Tag getNextTag();

	/**
	 * <p>
	 * 构建Tag对象
	 * </p>
	 * 
	 * <p>
	 * getNextTag()方法完成Tag字符串的读取后，调用该方法来构建Tag对象
	 * </p>
	 */
	protected void buildTag() {
		TagType type = getTagType();
		switch (type) {
		case HEAD:
			currTag = new HeadTag(currTagStr);
			break;
		case START:
			currTag = new StartTag(currTagStr);
			break;
		case END:
			currTag = new EndTag(currTagStr);
			break;
		case SELF_CLOSE:
			currTag = new SelfCloseTag(currTagStr);
			break;
		case CDATA:
			currTag = new CDataTag(currTagStr);
			break;
		case COMMENT:
			currTag = new CommentTag(currTagStr);
			break;
		case UNKNOW:
			currTag = new UnknowTag(currTagStr);
			break;
		default:
			currTag = null;
		}
	}

	/**
	 * 获取标签的类型
	 * 
	 * @return 标签类型
	 */
	protected TagType getTagType() {
		TagType type = TagType.NULL;

		if (null != currTagStr) {
			if (currTagStr.startsWith(Tag.END_TAG_FLAG)) {
				// 判定为尾标签
				type = TagType.END;
			} else if (currTagStr.endsWith(Tag.SELF_CLOSE_TAG_FLAG)) {
				// 判定为自闭标签
				type = TagType.SELF_CLOSE;
			} else if (currTagStr.startsWith(Tag.COMMENT_TAG_START)
					&& currTagStr.endsWith(Tag.COMMENT_TAG_END)) {
				// 判定为注释
				type = TagType.COMMENT;
			} else if (currTagStr.startsWith(Tag.HEAD_TAG_START)
					&& currTagStr.endsWith(Tag.HEAD_TAG_END)) {
				// 判定为头标签
				type = TagType.HEAD;
			} else if (currTagStr.startsWith(Tag.CDATA_TAG_START)) {
				// 判定为CData标签
				type = TagType.CDATA;
			} else if (currTagStr.startsWith(Tag.TAG_START)
					&& (-1 != currTagStr.indexOf(Tag.TAG_END))) {
				// 判定为开始标签
				type = TagType.START;
			} else {
				// 判定为未知标签
				type = TagType.UNKNOW;
			}
		}

		return type;
	}

	/**
	 * 清理方法。
	 * 
	 * 子类重写该方法以释放持有的资源
	 */
	abstract void clean();

}
